import javax.microedition.rms.RecordStore;
import java.io.*;
import java.util.Vector;
import javax.microedition.lcdui.*;

public class Resources {
	// array of all text strings
	public static String mStrings[];

	// options bits
	public static final int nOptFlg_NormalFnt = 0;
	public static final int nOptFlg_BoldFnt = 2; // Bold font with the same color

	// fonts
	//#if USE_SYSTEM_FONT
		private static Font mFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
		private static Font bFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_SMALL);
	//#else
		private static PFont mFont = new PFont();
	//#endif

	// high socres
	private static String highScoreNames[] = new String[10];
	private static int highScoreValues[] = new int[10];

	/**
	 *
	 */
	public final static String GetString(int n_id) {
		if (mStrings != null) {
			if ( (n_id >= 0) && (n_id < mStrings.length)) return mStrings[n_id];
		}
		return null;
	}

	/**
	 *
	 */
	public static void initCommonResources() {
		DataInputStream dis = null;

		System.gc();

		//#if !USE_SYSTEM_FONT
			// font init
			mFont.LoadCharset(FontsID.nFntID_EngBg);
			mFont.LoadCharset(FontsID.nFntID_EngSm);
			mFont.LoadCharset(FontsID.nFntID_Misc);
		//#endif
 
		// init pic-library
		PicDrawer.LoadPics();

		// tiles
		TileDrawer.LoadTiles();

		// animations
		Animation.LoadAnims("/res/anim.ani");

		// strings
		mStrings = new String[StringsID.nStrID_StrCount];
		try {
			dis = new DataInputStream(MTMMidlet.the_class.getResourceAsStream("/res/Strings.dat"));
			if (dis != null) {
				for (int i = 0; i < StringsID.nStrID_StrCount; i++) {
					//#if !USE_GAME_TIPS
						switch (i) {
							case StringsID.nStrID_TipLevel:
							case StringsID.nStrID_TipSpring:
							case StringsID.nStrID_TipFirewall:
							case StringsID.nStrID_TipDynamite:
							case StringsID.nStrID_TipPickaxe:
							case StringsID.nStrID_TipCrashingPlatform:
							case StringsID.nStrID_TipTeleport:
								dis.readUTF();
								mStrings[i] = "";
							break;

							default:
								mStrings[i] = dis.readUTF();
						}
					//#else
						mStrings[i] = dis.readUTF();
					//#endif
				}
				dis.close();
			}
		}
		catch(Exception ex) {
		}
		finally {
			dis = null;
			System.gc();
		}
	}

	/**
	 *
	 */
	public static void cleanMenuResources() {
		GameMenu.bTilesMatrix = null;
		//#if !IMGGROUP_12x12xLimited
			GameMenu.decorObjects = null;
		//#endif
		System.gc();
	}

	/**
	 *
	 */
	public static void initMenuResources() {
		DataInputStream dis = null;
		int i, j, iCount, jCount;
		byte rClassID;
		short rX, rY;

		System.gc();

		try {
			// message screen loading
			dis = new DataInputStream(MTMMidlet.the_class.getResourceAsStream("/res/screen.m2l"));
			if (dis != null) {
				dis.skipBytes( 8 );                    // amount of levels + offset of first level
				GameMenu.messPosY = dis.readShort();   // Y position of message (amount of ticks)
				//#if IMGGROUP_12x12 || IMGGROUP_12x12xLimited
					GameMenu.messPosY = (short)((GameMenu.messPosY * 12) / 18);
				//#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
					GameMenu.messPosY = (short)((GameMenu.messPosY * 24) / 18);
				//#elif IMGGROUP_36x36
					GameMenu.messPosY = (short)((GameMenu.messPosY * 36) / 18);
				//#endif
				dis.skipBytes( 4 );                    // starting point

				// matrix dim
				iCount = dis.readByte();
				jCount = dis.readByte();

				// tile matrix
				GameMenu.bTilesMatrix = new byte[iCount][jCount];
				for (i = 0; i < iCount; i++) {
					for (j = 0; j < jCount; j++) {
						GameMenu.bTilesMatrix[i][j] = dis.readByte();
					}
				}

				//#if !IMGGROUP_12x12xLimited
					// torches
					iCount = dis.readByte();
					if (iCount > 0) {
						GameMenu.decorObjects = new LevObj[iCount];
						for (i = 0; i < iCount; i++) {
							GameMenu.decorObjects[i] = new LevObj();
							rClassID = dis.readByte();
							rX = dis.readShort();
							rY = dis.readShort();
							//#if IMGGROUP_12x12
								rX = (short)((rX * 12) / 18);
								rY = (short)((rY * 12) / 18);
							//#elif IMGGROUP_24x24 || IMGGROUP_24x24xLimited
								rX = (short)((rX * 24) / 18);
								rY = (short)((rY * 24) / 18);
							//#elif IMGGROUP_36x36
								rX = (short)((rX * 36) / 18);
								rY = (short)((rY * 36) / 18);
							//#endif
							//#if USE_GAME_TIPS
								GameMenu.decorObjects[i].Init(i, ObjID.nObjID_DynCount + rClassID, rX, rY, null, null);
							//#else
								GameMenu.decorObjects[i].Init(i, ObjID.nObjID_DynCount + rClassID, rX, rY, null);
							//#endif
						}
					}
				//#endif
				dis.close();
			}
		}
		catch(Exception ex) {
		}
		finally {
			dis = null;
			System.gc();
		}
	}

	/**
	 *
	 */
	public static void cleanGameResources() {
		PicDrawer.mImages[1] = null;
		//#if SCREENGROUP_128x127xSpecial
			PicDrawer.mImages[3] = null;
		//#endif
		//#if PAUSE_MENU_BG_RASTER
			GameMenu.imgRastr = null;
		//#endif
		System.gc();
	}

	/**
	 *
	 */
	public static void initGameResources() {
		PicDrawer.mImages[1] = Resources.LoadImage("/res/p1");
		//#if SCREENGROUP_128x127xSpecial
			PicDrawer.mImages[3] = Resources.LoadImage("/res/p3");
		//#endif
		//#if PAUSE_MENU_BG_RASTER
			GameMenu.imgRastr = Resources.LoadImage("/res/rastr");
		//#endif
	}

	/**
	 *
	 */
	public static int stringWidth(String str, int n_opt_flg) {
		int w = mFont.stringWidth(str);
		if (((w != 0) && (n_opt_flg & (nOptFlg_BoldFnt)) != 0)) {
			w += 2;
		}
		return w;
	}

	/**
	 *
	 */
	public static int stringHeight(int n_opt_flg) {
		int h = mFont.getHeight();
		if (((h != 0) && (n_opt_flg & (nOptFlg_BoldFnt)) != 0)) {
			h += 2;
		}
		return h;
	}

	/**
	 *
	 */
	public static int stringWidth(int n_str_id, int n_opt_flg) {
		if (n_str_id >= 0) return stringWidth(mStrings[n_str_id], n_opt_flg);
		return 0;
	}

	private static String strNum = "";
	private static int nScoreDig[] = {
										PicID.nPicID_0b, PicID.nPicID_1b, PicID.nPicID_2b,
										PicID.nPicID_3b, PicID.nPicID_4b, PicID.nPicID_5b,
										PicID.nPicID_6b, PicID.nPicID_7b, PicID.nPicID_8b, PicID.nPicID_9b
									 };


	/**
	 *
	 */
	public static int scoreStringHeight() {
		return PicDrawer.GetPicHeight(nScoreDig[0]);
	}

	/**
	 *
	 */
	public static int scoreStringWidth( String str ) {
		int w = 0;
		int len = str.length();
		for (int i=0; i<len; i++) {
			int ndx = str.charAt(i) - '0';
			if ((ndx >= 0) && (ndx < nScoreDig.length)) {
				w += PicDrawer.GetPicWidth( nScoreDig[ndx] );
			}
		}
		return w;
	}

	/**
	 *
	 */
	public static void DrawScoreNumber( Graphics g, int x, int y, int n_number, boolean full, int anchor ) {
		int len, start, ndx;

		strNum = Integer.toString( n_number );
		len = strNum.length();
		if (full) {
			start = len - 3;
		}
		else {
			start = 0;
		}
		if ((anchor & ( Graphics.HCENTER ) ) == Graphics.HCENTER) {
			x -= ( scoreStringWidth( strNum ) >> 1 );
		}
		if ((anchor & ( Graphics.RIGHT ) ) == Graphics.RIGHT) {
			x -= scoreStringWidth( strNum );
		}
		if ((anchor & ( Graphics.BASELINE ) ) == Graphics.BASELINE) {
			y -= ( scoreStringHeight() >> 1 );
		}
		if ((anchor & ( Graphics.BOTTOM ) ) == Graphics.BOTTOM) {
			y -= scoreStringHeight();
		}
		if ((anchor & ( Graphics.VCENTER ) ) == Graphics.VCENTER) {
			y -= ( scoreStringHeight() >> 1 );
		}
		for (int i=start; i<len; i++) {
			if (i < 0) {
				ndx = 0;
			}
			else {
				ndx = strNum.charAt(i) - '0';
			}
			if ((ndx >= 0) && (ndx<nScoreDig.length)) {
				PicDrawer.DrawPic(g, x, y, nScoreDig[ndx], Graphics.TOP|Graphics.LEFT);
				x += PicDrawer.GetPicWidth( nScoreDig[ndx] );
			}
		}
	}

	/**
	 *
	 */
	public static void DrawString(Graphics g, String s, int x, int y, int anchor, int n_opt_flg) {
		//#if USE_SYSTEM_FONT
			if ((n_opt_flg & nOptFlg_BoldFnt) != 0) {
				g.setFont(bFont);
			}
			else {
				g.setFont(mFont);
			}

			g.setColor(0xB05020); //0xC08000//0xAD7124
			g.setClip(0, 0, MTMCanvas.width, MTMCanvas.height);
			try {
				g.drawString(s, x, y, anchor);
			}
			catch(Exception ex) {
			}
		//#else
			if ((n_opt_flg & nOptFlg_BoldFnt) != 0) {
				mFont.drawString(g, s, x - 1, y - 1, anchor);
				mFont.drawString(g, s, x + 1, y + 1, anchor);
			}
			mFont.drawString(g, s, x, y, anchor);
		//#endif
	}

	/**
	 *
	 */
	public static void DrawString(Graphics g, int n_str_id, int x, int y, int anchor, int n_opt_flg) {
		if (n_str_id >= 0) {
			DrawString(g, mStrings[n_str_id], x, y, anchor, n_opt_flg);
		}
	}

	/**
	 *
	 */
	public static void stringFragmentation(Vector v_out, String str, int n_fnt_flags, int n_wnd_width) {
		String str_cur_string = "";
		String str_cur_word;
		boolean bl_end_of_string = false;
		int n_start = 0;
		int n_end = 0;
		int len = 0;
		int n_cur_str_width = 0;
		// additional fragmentation with special symbol
		int spec;

		while (bl_end_of_string != true) {
			n_end = str.indexOf(' ', n_start);

			if (n_end == -1) {
				n_end = str.length();
				bl_end_of_string = true;
			}
			spec = str.indexOf('|', n_start);
			if (spec != -1) {
				if (spec > n_end) spec = -1;
			}
			if (spec == -1)
				str_cur_word = str.substring(n_start, n_end);
			else
				str_cur_word = str.substring(n_start, spec);
			if (n_cur_str_width == 0)
				len = n_cur_str_width + stringWidth(str_cur_word, n_fnt_flags);
			else
				len = n_cur_str_width + stringWidth(" " + str_cur_word, n_fnt_flags);
			if (len <= n_wnd_width) {
				if (n_cur_str_width == 0)
					str_cur_string += str_cur_word;
				else
					str_cur_string += " " + str_cur_word;
				n_cur_str_width = len;
				if (spec != -1) {
					v_out.addElement(str_cur_string);
					str_cur_string = "";
					n_cur_str_width = 0;
					n_end = spec;
				}
				if (bl_end_of_string == true) v_out.addElement(str_cur_string);
			}
			else {
				v_out.addElement(str_cur_string);
				len = stringWidth(str_cur_word, n_fnt_flags);
				if (len > n_wnd_width) {
					while (len > n_wnd_width) {
						//string is too large
						n_end--;
						str_cur_word = str.substring(n_start, n_end);
						len = stringWidth(str_cur_word, n_fnt_flags);
						bl_end_of_string = false;
					}
					n_end--;
				}

				str_cur_string = str_cur_word;
				n_cur_str_width = stringWidth(str_cur_string, n_fnt_flags);

				if (bl_end_of_string == true) v_out.addElement(str_cur_string);
			}
			n_start = n_end + 1;
		}
	}

	/**
	 *
	 */
	public final static Image LoadImage(String fileName) {
		Image pImage = null;
		System.gc();
		try {
			pImage = Image.createImage(fileName + ".png");
		}
		catch(Exception e) {
			// System.out.println("LoadImage() - " + fileName + " - " + e.toString());
		}
		return pImage;
	}

	/**
	 *
	 */
	public static void saveSettings() {
		try {
			RecordStore rs = RecordStore.openRecordStore("mtm2", true);

			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			DataOutputStream dos = new DataOutputStream(baos);

			// write settings
			dos.writeInt(Hero.m_nLevelMax);
			GameMenu.editStr.setLength(GameMenu.editorLength);
			dos.writeUTF(GameMenu.editStr.toString());
			//#if USE_SOUND_VOLUME_CONTROL
				dos.writeByte(MTMCanvas.volumeLevel);
			//#endif

			byte[] data = baos.toByteArray();
			dos.close();

			if (rs.getNumRecords() == 0)
				rs.addRecord(data, 0, data.length);
			else
				rs.setRecord(1, data, 0, data.length);

			rs.closeRecordStore();
		}
		catch(Exception ex) {
		}
	}

	/**
	 *
	 */
	public static void loadSettings() {
		try {
			RecordStore rs = RecordStore.openRecordStore("mtm2", true);

			Hero.m_nLevelMax = 0;
			GameMenu.editStr.setLength(0);
			//#if USE_SOUND_VOLUME_CONTROL
				MTMCanvas.volumeLevel = -1;
			//#endif

			if (rs.getNumRecords() != 0) {
				byte[] data = rs.getRecord(1);
				ByteArrayInputStream bais = new ByteArrayInputStream(data);
				DataInputStream dis = new DataInputStream(bais);

				// read settings
				Hero.m_nLevelMax = dis.readInt();
				String name = dis.readUTF();
				GameMenu.editStr.append(name);
				GameMenu.editorLength = name.length();
				//#if USE_SOUND_VOLUME_CONTROL
					MTMCanvas.volumeLevel = dis.readByte();
				//#endif

				dis.close();
				//#if SCORE_SAVE_RMS
					if (rs.getNumRecords() != 1) {
						data = rs.getRecord(2);
						bais = new ByteArrayInputStream(data);
						dis = new DataInputStream(bais);

						for (int i=0; i<highScoreValues.length; i++) {
							highScoreValues[i] = dis.readInt();
							highScoreNames[i] = dis.readUTF();
						}
						dis.close();
					}
				//#endif
			}
			rs.closeRecordStore();
		}
		catch(Exception ex) {
		}
	}

	/**
	 *
	 */
	public static void loadHighScores(Vector vText) {
		vText.removeAllElements();
		//#if SCORE_SAVE_RMS
			for (int i=0; i<highScoreValues.length; i++) {
				if (highScoreValues[i] == 0) {
					break;
				}
				vText.insertElementAt(highScoreNames[i], i);
				vText.addElement(Integer.toString(highScoreValues[i]));
			}
		//#else
			int scores = 10;
			for (int i=0; i<scores; i++) {
				vText.insertElementAt("name", i);
				vText.addElement(Integer.toString(i));
			}
		//#endif
	}                                                      

	/**
	 *
	 */
	public static boolean uploadScore(int score) {
		//#if SCORE_SAVE_RMS
			int i, j;
			for (i = highScoreValues.length - 1; (i >= 0) && ((score > highScoreValues[i]) || (highScoreValues[i] == 0)); i--);
			if (i == (highScoreValues.length - 1)) {
				return true;
			}
			// shift scores
			for (j = highScoreValues.length - 1; (j > i) && (j >= 1); j--) {
				highScoreNames[j] = highScoreNames[j - 1];
				highScoreValues[j] = highScoreValues[j - 1];
			}

			highScoreNames[i+1] = GameMenu.editStr.toString();
			highScoreValues[i+1] = score;

			// save score
			try {
				RecordStore rs = RecordStore.openRecordStore("mtm2", true);

				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				DataOutputStream dos = new DataOutputStream(baos);

				// write scores
				for (i = 0; i < highScoreValues.length; i++) {
					dos.writeInt(highScoreValues[i]);
					if (highScoreNames[i] != null) 
						dos.writeUTF(highScoreNames[i]);
					else 
						dos.writeUTF("");
				}
				byte[] data = baos.toByteArray();
				dos.close();

				if ( rs.getNumRecords() == 1 )
					rs.addRecord(data, 0, data.length);
				else
					rs.setRecord(2, data, 0, data.length);

				rs.closeRecordStore();
			}
			catch(Exception ex) {
			}
			return true;
		//#else
			return false;
		//#endif
	}
}
